A standard way to communicate between two processes A and B (running on the same machine or running on different machines) is to send a message. Often, for example, it is desirable to enable process A to send a message to process B asking process B to execute code on behalf of process A. Typically, process A must have knowledge of a port or contact point for process B in order to do this.
One way to enable process A to call process B is via a remote procedure call (RPC). A remote procedure call enables a process on one computer to cause code to be executed in another process on the same or on a different computer, without requiring explicit code to be written by a developer or programmer to perform that particular call. An RPC is initiated by the caller process (client) sending a request message to a remote system or second process (server) to execute a certain procedure using supplied arguments. A result message is returned to the caller. For example, in a remote procedure call, a function call may be made by process A, in which the name of the procedure that process B is to execute on behalf of process A and a set of parameters for the procedure, are specified. Process B executes the code and returns a message to process A. When the code in question is written using principles of object-oriented programming, RPC is sometimes referred to as remote invocation or remote method invocation.
A remote procedure call typically follows a particular protocol (another way of saying this is “it uses a particular interface”) so that potentially unrelated processes can communicate. The protocol or interface define the methods and the values which the processes agree upon in order to cooperate.
The procedure of transforming the function call into a message is called marshalling. Marshalling may include gathering data from one or more applications or non-contiguous sources in computer storage, putting the data pieces into a message buffer, and organizing or converting the data into a format that is prescribed for a particular receiver or programming interface. Marshalling typically converts what the code in process A sees as a function call into a message to be sent to process B. The message typically includes the name of the function and a set of parameters, coded in a way that process B understands. Process B receives the message and has to transform the message into a call to process B's internal function. The process of converting a message into a function call is called unmarshalling. The piece of code that performs marshalling in process A is called a proxy and typically resides in the client process. The corresponding piece of code on the server side that performs unmarshalling is called a stub.
Within the context of object oriented programming, process A and process B can be viewed as objects encapsulating data and functions. Some well-known technologies that take this approach are Sun Microsystem's JAVA and Microsoft's COM and DCOM. That is, process B may be viewed as a container for one or multiple objects, whose methods are the functions invoked by process A. In object oriented systems, therefore, process A invokes a method of a particular object of process B instead of invoking a function in process B. To do this, process A must have some way of identifying the object in process B that process A wishes to invoke.
The data stored in process A which enables process A to identify the object of process B is known as a reference to the object. The reference stores information concerning how to locate the object: that is, the reference must be sufficient to identify the process and within the process to identify the object whose method is to be invoked.
When process B provides a reference to one of its objects to process A and process A invokes that object, typically process B keeps track of that invocation. In fact, typically process B will keep track of how many invocations to the object are outstanding in all the processes to which a reference to the object has been provided. When there are no more outstanding invocations, process B may perform clean-up operations and so on, so that the information that there are no outstanding invocations to process B's object is information that process B would find interesting and helpful. Sometimes, however, after process A invokes process B's object, it may become necessary or desirable to cancel the invocation of that object. However, because time may elapse between the sending of the cancel request and the actual cancellation, a time window for another process to invoke the object is provided. Thus process B's invocation tracking information may be incorrect—process B may perform processing that should be done only when there are no more outstanding references to the object but in the meantime a new invocation may have been sent. That is, an improperly handled cancellation may create race conditions. It would be helpful if there were a mechanism that would prevent these inconsistencies.